Skip to content

Conversation

@Cassiiopeia
Copy link
Member

@Cassiiopeia Cassiiopeia commented Feb 5, 2026

Summary by CodeRabbit

  • 새로운 기능
    • 알림 설정 화면이 추가되었습니다. 마케팅, 활동, 채팅, 콘텐츠, 거래 5가지 알림을 각각 켜고 끌 수 있습니다.
    • 각 알림 항목에 대해 한국어 제목과 설명이 제공됩니다.
  • 사용성
    • 기존 알림 화면의 설정 버튼이 알림 설정 화면으로 바로 이동합니다.
  • 동작
    • 토글 변경은 화면에 즉시 반영되고 서버에 저장됩니다. 저장 실패 시 변경이 되돌려집니다.
    • 로딩 상태 표시(CircularProgressIndicator)가 추가되었습니다.
  • 기타
    • 알림 관련 모델과 API, 토글 색상이 일부 업데이트되었습니다.

@coderabbitai
Copy link

coderabbitai bot commented Feb 5, 2026

Walkthrough

알림 설정 타입과 설정 화면을 추가하고, 기존 알림 화면의 설정 탭을 새 설정 화면으로 네비게이션하도록 변경했습니다. 또한 worktree 관리 스크립트와 관련 문서들이 원격 브랜치 확인·생성 및 작업트리 루틴을 원격 인식 방식으로 대규모 리팩터링·기능 확장이 이루어졌습니다.

Changes

Cohort / File(s) Summary
알림 타입 정의
lib/enums/notification_setting_type.dart
새 enum NotificationSettingType 및 각 케이스에 대한 한국어 title/description 확장 추가.
알림 화면 및 설정 UI
lib/screens/notification_settings_screen.dart, lib/screens/notification_screen.dart, lib/screens/my_page_tab_screen.dart
새 Stateful 화면 NotificationSettingsScreen 추가(5개 토글), 기존 화면에서 해당 화면으로 네비게이션으로 변경. 초기값 로드 및 토글 변경 시 API 호출 로직 포함.
API/모델 연동
lib/models/apis/objects/member.dart, lib/models/apis/objects/member.g.dart, lib/services/apis/member_api.dart
Member 모델에 4개 알림 필드 추가 및 JSON 직렬화 업데이트. 기존 단일 업데이터를 대체하는 updateNotificationSetting(...) API 도입(다중 optional 필드, null-aware 페이로드 생성).
UI 위젯 색상 조정
lib/widgets/common/completed_toggle_switch.dart
토글 비활성 색상 상수 변경(0x33FFFFFFAppColors.opacity40White).
worktree 도구 — 코드 변경
.claude/scripts/worktree_manager.py, .cursor/scripts/worktree_manager.py
버전 1.0.4→1.1.0, Windows/인코딩 처리 강화, 원격 브랜치 검사·fetch·로컬/원격 기반 브랜치 생성, 다수 유틸(원격 검사, fetch, 브랜치 생성, worktree 경로/생성/검사 등) 추가, 워크플로우 재구성 및 메시지 개선.
worktree 도구 — 문서/명령 변경
.claude/commands/init-workflow.md, .cursor/commands/init-workflow.md
브랜치 부재 시 원격(origin) 확인 후 fetch/트래킹 또는 로컬 생성으로 동작 흐름 갱신 문서화 및 일부 출력/인자 포맷 조정.

Sequence Diagram(s)

sequenceDiagram
  participant User as User
  participant CLI as CLI/Script
  participant Git as Git (local/remote)
  participant FS as Filesystem

  rect rgba(128, 203, 196, 0.5)
  User->>CLI: 요청(브랜치 이름)
  CLI->>Git: 로컬 브랜치 존재 여부 조회
  Git-->>CLI: 로컬 없음
  CLI->>Git: fetch origin
  Git-->>CLI: origin 브랜치 존재 여부 응답
  alt origin에 브랜치 존재
    CLI->>Git: origin/branch에서 로컬 트래킹 브랜치 생성
  else 원격에 없음
    CLI->>Git: 현재 브랜치에서 새 로컬 브랜치 생성
  end
  CLI->>FS: worktree 경로 계산 및 디렉터리 준비
  FS-->>CLI: 디렉터리 확인/생성 완료
  CLI->>Git: worktree 추가(create/add)
  Git-->>CLI: worktree 생성 성공
  CLI->>User: 결과 출력 (경로/성공)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • 드롭다운 디자인 변경 #451 — enum 및 알림 UI 변경과 관련된 유사한 enum/알림 화면 수정이 포함되어 있어 코드 수준 연관 가능성 높음.

Suggested reviewers

  • SeoHyun1024
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 알림 설정 페이지 연결이라는 주요 변경사항을 명확하게 설명하며, 변경사항 전반을 잘 대표합니다.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 20260127_#452_알림_보관함_페이지에서_톱니바퀴_연결시_알림페이지_설정_페이지_연결

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 8, 2026

✅ 프로젝트 빌드 성공

APK 빌드가 완료되었습니다.

…연결시_알림페이지_설정_페이지_연결' into 20260127_#452_알림_보관함_페이지에서_톱니바퀴_연결시_알림페이지_설정_페이지_연결
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.claude/scripts/worktree_manager.py:
- Line 3: The file has inconsistent version strings: the header "Git Worktree
Manager v1.1.0" and the docstring/metadata "Version: 1.0.4" differ; update the
latter to match the header (or vice versa) so both show the same version (e.g.,
change "Version: 1.0.4" to "Version: 1.1.0"). Locate the top banner "Git
Worktree Manager v1.1.0" and the docstring/metadata line containing "Version:
1.0.4" in worktree_manager.py and make them identical; also scan for any other
version constants or comments in the file and standardize them to the chosen
version.

In @.cursor/scripts/worktree_manager.py:
- Line 3: The docstring/version strings are inconsistent: the header string "Git
Worktree Manager v1.1.0" and the docstring line "Version: 1.0.4" differ; update
the docstring entry "Version: 1.0.4" to "Version: 1.1.0" (or vice versa if
v1.0.4 is the intended release) and scan the file for any other occurrences of
those version literals to keep them all consistent (look for the header "Git
Worktree Manager v1.1.0" and the docstring "Version: 1.0.4").
🧹 Nitpick comments (8)
.cursor/commands/init-workflow.md (1)

96-108: lines[i-1] 접근 시 경계 조건 방어 코드 부재

i == 0일 경우 lines[-1]에 접근하게 되어 잘못된 경로를 반환할 수 있습니다. git worktree list --porcelain 출력 형식상 branch 줄이 첫 번째에 올 가능성은 낮지만, 문서 내 예시 코드이므로 방어 코드를 추가하면 더 안전합니다.

🛡️ 제안
     for i, line in enumerate(lines):
         if line.startswith(f'branch refs/heads/{branch_name}'):
-            worktree_path = lines[i-1].replace('worktree ', '')
+            if i > 0:
+                worktree_path = lines[i-1].replace('worktree ', '')
             break
.cursor/scripts/worktree_manager.py (2)

260-265: lstrip('* ')는 문자열이 아닌 개별 문자를 제거합니다

lstrip('* ')*, 각각의 문자를 왼쪽에서 제거합니다. 예를 들어 " special""pecial"이 됩니다. 현재 브랜치명 패턴(날짜 접두사)상 실질적 문제가 될 가능성은 낮지만, 의도대로라면 prefix 제거 방식을 사용하는 것이 정확합니다.

🔧 수정 제안
-        branches = [line.strip().lstrip('* ') for line in stdout.split('\n')]
+        branches = [line.strip().removeprefix('* ').strip() for line in stdout.split('\n')]

622-651: fetch_remote() 실패 시에도 remote_branch_exists를 호출합니다

Line 628에서 fetch_remote()의 반환값을 무시하고 있어, fetch가 실패(네트워크 오류 등)해도 stale 데이터 기반으로 리모트 브랜치 존재 여부를 판단합니다. 이로 인해 실제로는 리모트에 존재하는 브랜치를 못 찾거나, 이미 삭제된 리모트 브랜치를 찾는 오동작이 발생할 수 있습니다.

fetch 실패 시 경고 로그를 남기는 현재 동작도 나쁘지 않지만, 최소한 코멘트로 의도적 fallthrough임을 명시하면 좋겠습니다.

🔧 수정 제안
         # 리모트에서 최신 정보 가져오기
-        fetch_remote()
+        # fetch 실패 시에도 기존 캐시된 리모트 정보로 계속 진행
+        fetch_remote()  # best-effort; uses cached remote refs on failure
.claude/scripts/worktree_manager.py (5)

1-22: .cursor/scripts/worktree_manager.py와 거의 동일한 코드 중복

이 파일은 .cursor/scripts/worktree_manager.py와 들여쓰기(2-space vs 4-space)만 다르고 로직이 동일합니다. 700줄 이상의 코드가 두 곳에서 유지보수되어야 하므로 향후 변경 시 불일치가 발생할 위험이 높습니다.

공통 모듈을 하나의 위치에 두고 두 환경에서 참조하거나, 심볼릭 링크를 사용하는 것을 고려해 주세요.


41-42: try-except-pass에서 예외가 무시됩니다

Ruff S110에서 지적된 대로, 래핑 실패 시 예외를 완전히 무시하고 있습니다. 최소한 logging.debug 등으로 남기면 디버깅에 도움이 됩니다.


444-448: 미사용 변수 stdout

Ruff RUF059에서 지적된 대로, stdout이 사용되지 않습니다. 관례에 따라 _로 대체하세요.

🔧 수정 제안
-  success, stdout, stderr = run_git_command(
+  success, _, stderr = run_git_command(

586-586: 플레이스홀더 없는 f-string

Ruff F541에서 지적된 대로, Lines 586과 590에 f 접두사가 불필요합니다.

🔧 수정 제안
-      print(f'      $env:GIT_BRANCH_NAME = "브랜치명"')
+      print('      $env:GIT_BRANCH_NAME = "브랜치명"')
-      print(f'      $env:BRANCH_NAME_FILE = "branch_name.txt"')
+      print('      $env:BRANCH_NAME_FILE = "branch_name.txt"')

Also applies to: 590-590


186-193: 리스트 연결 방식 개선

Ruff RUF005에서 제안한 대로, ['git'] + args 대신 ['git', *args]가 더 관용적입니다.

🔧 수정 제안
     result = subprocess.run(
-      ['git'] + args,
+      ['git', *args],
       capture_output=True,

# -*- coding: utf-8 -*-
"""
Git Worktree Manager v1.0.4
Git Worktree Manager v1.1.0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

docstring 내 버전 불일치 (.cursor 버전과 동일 이슈)

Line 3은 v1.1.0, Line 21은 Version: 1.0.4입니다. 통일이 필요합니다.

🔧 수정 제안
 Author: Cursor AI Assistant
-Version: 1.0.4
+Version: 1.1.0

Also applies to: 21-21

🤖 Prompt for AI Agents
In @.claude/scripts/worktree_manager.py at line 3, The file has inconsistent
version strings: the header "Git Worktree Manager v1.1.0" and the
docstring/metadata "Version: 1.0.4" differ; update the latter to match the
header (or vice versa) so both show the same version (e.g., change "Version:
1.0.4" to "Version: 1.1.0"). Locate the top banner "Git Worktree Manager v1.1.0"
and the docstring/metadata line containing "Version: 1.0.4" in
worktree_manager.py and make them identical; also scan for any other version
constants or comments in the file and standardize them to the chosen version.

# -*- coding: utf-8 -*-
"""
Git Worktree Manager v1.0.4
Git Worktree Manager v1.1.0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

docstring 내 버전 불일치

Line 3에서는 v1.1.0으로 표시되지만, Line 21에서는 Version: 1.0.4로 남아 있습니다. 하나로 통일해야 합니다.

🔧 수정 제안
 Author: Cursor AI Assistant
-Version: 1.0.4
+Version: 1.1.0
 """

Also applies to: 21-21

🤖 Prompt for AI Agents
In @.cursor/scripts/worktree_manager.py at line 3, The docstring/version strings
are inconsistent: the header string "Git Worktree Manager v1.1.0" and the
docstring line "Version: 1.0.4" differ; update the docstring entry "Version:
1.0.4" to "Version: 1.1.0" (or vice versa if v1.0.4 is the intended release) and
scan the file for any other occurrences of those version literals to keep them
all consistent (look for the header "Git Worktree Manager v1.1.0" and the
docstring "Version: 1.0.4").

@github-actions
Copy link
Contributor

github-actions bot commented Feb 8, 2026

✅ 프로젝트 빌드 성공

APK 빌드가 완료되었습니다.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 8, 2026

✅ 프로젝트 빌드 성공

APK 빌드가 완료되었습니다.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 8, 2026

✅ 프로젝트 빌드 성공

APK 빌드가 완료되었습니다.

Copy link
Collaborator

@SeoHyun1024 SeoHyun1024 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확인했습니다

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@lib/screens/notification_settings_screen.dart`:
- Around line 38-58: In _loadNotificationSettings(), handle the case where
response.member is null so _isLoading is cleared; if response.member == null
(but the API call succeeded) call setState to set _isLoading = false and
optionally initialize the notification flags (_isMarketingEnabled,
_isActivityEnabled, _isChatEnabled, _isContentEnabled, _isTransactionEnabled) to
safe defaults, ensuring the mounted check and existing setState usage remain
consistent so the UI stops showing the loading spinner even when response.member
is null.
🧹 Nitpick comments (4)
lib/widgets/common/completed_toggle_switch.dart (1)

36-39: 기존 코드에서 Colors.whiteColors.black 직접 사용

이번 변경과 직접 관련은 없지만, Line 36의 Colors.white와 Line 39의 Colors.black.withAlpha(64)AppColors 상수 대신 직접 사용되고 있습니다. 코딩 가이드라인에 따라 AppColors를 사용해야 합니다.

♻️ AppColors 사용으로 변경 제안
-                  color: Colors.white,
+                  color: AppColors.textColorWhite,

As per coding guidelines, "Always use AppColors for colors; direct Color code usage is forbidden in Dart files".

lib/screens/notification_settings_screen.dart (2)

138-213: switch 문이 3회 중복 사용됨 — Map 기반 접근으로 간소화 가능

_getSettingValue, _onSettingChanged, _updateNotificationSetting에서 동일한 switch 패턴이 반복됩니다. 설정 값을 Map으로 관리하면 코드 중복을 줄이고 새 설정 타입 추가 시 변경 포인트를 최소화할 수 있습니다.


188-212: API 실패 시 사용자에게 피드백 없음

토글이 조용히 원복되기만 하면 사용자는 설정 변경 실패를 인지하기 어렵습니다. 스낵바 등으로 실패를 알려주는 것을 권장합니다.

lib/services/apis/member_api.dart (1)

244-273: late MemberResponseonSuccess 미호출 시 LateInitializationError를 발생시킬 수 있음

sendMultipartRequest가 예외를 던지지 않으면서 onSuccess도 호출하지 않는 경우(예: 4xx/5xx 응답), memberResponse가 초기화되지 않은 상태로 반환되어 런타임 에러가 발생합니다. 호출부(_updateNotificationSetting)에서 try-catch로 감싸고 있어 즉시 크래시로 이어지진 않지만, 에러 원인 파악이 어려울 수 있습니다.

기존 메서드(getMemberInfo 등)에도 동일한 패턴이 있으므로 향후 전체적으로 개선하는 것을 권장합니다.

Comment on lines +38 to +58
Future<void> _loadNotificationSettings() async {
try {
final response = await _memberApi.getMemberInfo();
final Member? member = response.member;
if (member != null && mounted) {
setState(() {
_isMarketingEnabled = member.isMarketingInfoAgreed ?? false;
_isActivityEnabled = member.isActivityNotificationAgreed ?? false;
_isChatEnabled = member.isChatNotificationAgreed ?? false;
_isContentEnabled = member.isContentNotificationAgreed ?? false;
_isTransactionEnabled = member.isTradeNotificationAgreed ?? false;
_isLoading = false;
});
}
} catch (e) {
debugPrint('알림 설정 로딩 실패: $e');
if (mounted) {
setState(() => _isLoading = false);
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

member가 null일 경우 로딩이 영원히 해제되지 않음

getMemberInfo()가 성공하지만 response.membernull인 경우, _isLoadingtrue로 유지되어 사용자에게 무한 로딩 스피너가 표시됩니다.

🐛 수정 제안
     final Member? member = response.member;
-    if (member != null && mounted) {
+    if (mounted) {
       setState(() {
-        _isMarketingEnabled = member.isMarketingInfoAgreed ?? false;
-        _isActivityEnabled = member.isActivityNotificationAgreed ?? false;
-        _isChatEnabled = member.isChatNotificationAgreed ?? false;
-        _isContentEnabled = member.isContentNotificationAgreed ?? false;
-        _isTransactionEnabled = member.isTradeNotificationAgreed ?? false;
+        if (member != null) {
+          _isMarketingEnabled = member.isMarketingInfoAgreed ?? false;
+          _isActivityEnabled = member.isActivityNotificationAgreed ?? false;
+          _isChatEnabled = member.isChatNotificationAgreed ?? false;
+          _isContentEnabled = member.isContentNotificationAgreed ?? false;
+          _isTransactionEnabled = member.isTradeNotificationAgreed ?? false;
+        }
         _isLoading = false;
       });
     }
🤖 Prompt for AI Agents
In `@lib/screens/notification_settings_screen.dart` around lines 38 - 58, In
_loadNotificationSettings(), handle the case where response.member is null so
_isLoading is cleared; if response.member == null (but the API call succeeded)
call setState to set _isLoading = false and optionally initialize the
notification flags (_isMarketingEnabled, _isActivityEnabled, _isChatEnabled,
_isContentEnabled, _isTransactionEnabled) to safe defaults, ensuring the mounted
check and existing setState usage remain consistent so the UI stops showing the
loading spinner even when response.member is null.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 9, 2026

✅ 프로젝트 빌드 성공

APK 빌드가 완료되었습니다.

@SeoHyun1024 SeoHyun1024 merged commit 69f52fe into main Feb 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants